/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "Widget.h"
#include "底层绘图/S_纹理.h"

#include <数据工具库.h>
#include <字符串数值互换.h>
#include <几何计算.h>
#include <file_文件名数据.h>
#include <字符串/str_分割.h>

#include <ppl.h>
#include <ft2build.h>
#include <freetype.h>
#include <nmmintrin.h>

#include "布局.h"

#include "底层绘图/intern/Vulkan/Vulkan框架.h"
#include "面/intern/矢量绘图着色材质.h"
#include "底层绘图/intern/Vulkan/线管/着色器.h"
#include "core/网格辅助计算.h"

#include "UI/UI.h"







#include FT_FREETYPE_H



E_鼠标样式				C_Widget::g_鼠标样式 = E_鼠标样式::e_鼠标样式_默认;
S_鼠标					C_Widget::g_鼠标 = {};
S_键盘					C_Widget::g_键盘 = {};
bool					C_Widget::g_是否打开了弹出窗口 = false;
//bool					C_Widget::G清除焦点组件 = false;
std::set<S_键位映射*>	C_Widget::g_键位映射容器;


//static vec4			g_当前窗口区域;

static int32			g输入法正在输入的字符 = 0;
static ivec2			g输入法窗口位置 = {};
static bool				g是否使用输入法 = false;
static bool				g输入法有输入 = false;
static std::u16string	g输入法文本;

static std::set<S_关联组件*> g关联组件容器;

std::vector<std::u16string>	C_Widget管理::m_拖放文件名;


static C_Widget管理* g当前窗口GM = nullptr;

uvec2		C_文本框::g选择文本ID区间 = {};
vec2		C_文本框::g光标绘制位置 = {};





static bool f_部件更新阶段回调() {
	return true;
}

static S_需更新部件 f_get变换需修改部件(C_Widget* self) {
	return { self->m_子组件.data(), uint32(self->m_子组件.size()) };
}


static E_事件是否传递 f_鼠标按钮空事件(C_Widget* self, const E_鼠标按钮& 按钮) {
	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 f_鼠标滚轮空事件(C_Widget* self, const S_鼠标& 轮值) {
	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 f_鼠标移动空事件(C_Widget* self, const ivec4& value) {
	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 f_鼠标进入空事件(C_Widget* self, const S_鼠标& 轮值) {
	std::cout << "f_鼠标进入空事件:" << self->m_TypeName << std::endl;
	return E_事件是否传递::e_事件传递_继续;
}
static E_事件是否传递 f_鼠标移除空事件(C_Widget* self, const S_鼠标& 轮值) {
	std::cout << "f_f_鼠标移除空事件" << self->m_TypeName << std::endl;
	return E_事件是否传递::e_事件传递_继续;
}




static inline void f_Widget事件初始化(C_Widget* w) {
	w->mf_鼠标按键按下 = f_鼠标按钮空事件;
	w->mf_鼠标按键放开 = f_鼠标按钮空事件;
	w->mf_鼠标按键双击 = f_鼠标按钮空事件;
	w->mf_鼠标点击 = f_鼠标按钮空事件;
	w->mf_鼠标滚轮 = f_鼠标滚轮空事件;
	w->mf_鼠标移动 = f_鼠标移动空事件;

	w->mf_行文本输入 = nullptr;
	w->mf_鼠标按键双击 = nullptr;
	w->mf_键盘按键敲击 = nullptr;
	w->mf_按键字符输入 = nullptr;
	
	
	w->mf_开始拖拽 = nullptr;
	w->mf_结束拖拽 = nullptr;
	w->mf_拖拽 = 0;

	w->mf_布局 = nullptr;
	w->mf_绘制 = nullptr;
	w->mf_变换 = nullptr;
	w->mf_当前部件属性修改 = nullptr;
	w->mf_文件处理回调 = nullptr;

	w->mf_鼠标进入 = 0;
	w->mf_鼠标离开 = 0;

	w->mf_动画 = 0;
	w->mf_打开关闭 = 0;
	
}




C_Widget::C_Widget(S_UI渲染环境* ctx) : m_扩展视口属性(0), 
	m_GM(nullptr), 
	m_UserData(nullptr),

	mf_绘制(nullptr),
	mf_拖拽(nullptr),

	m_区域帧缓存根(nullptr),
	m_区域链接根(nullptr),
	m_画布(nullptr),
	m_渲染层(0),
	m_实例ID(0),
	m_窗口层(0),
	//m_层级ID(0),
	m_更新下层绘制(true),

	m_父部件(nullptr),

	m_显示(true),
	m_拾取(true),
	m_被裁剪(false),

	m_Type(0)
{
	if (ctx == nullptr) {
		std::cout<<"\n";
	}
	f_Widget事件初始化(this);
	
	mf_get更新组件 = f_get变换需修改部件;
	
	
	m_自定义属性 = {};
	m_UIctx = ctx;
	
	//m_子部件裁剪使用父裁剪区域 = false;
	m_使用父组件裁剪 = false;
	m_更新绘制属性 = true;
	m_开启渲染 = true;
	m_引用画布 = false;
	

	m_绘制标题 = false;
	m_拖放阻止鼠标进出事件 = false;
	m_强制焦点 = false;
	m_延申比	= 1.0f;
	m_是否延展	= { 0,0 };
	m_间隔宽度	= 1;

	m_Pos			= { 0.0f, 0.0f };
	m_GlobalLoc		= { 0.0f, 0.0f };
	m_GlobalScale	= {1,1};
	m_Size			= { 10.0f, 10.0f };
	m_Scale			= { 1.0f, 1.0f };
	m_裁剪大小		= { 0, 0, 30, 30 };
	
	m_OriginalPos	= m_Pos * m_Scale;
	m_OriginalSize	= m_Size * m_Scale;

	m_ColorA = S_2D颜色包({255,255,255,255}, 0, 0, 0);
	if (m_UIctx) {
		m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面矩形;
	}
	else {
		m_图元形状 = nullptr;
	}
	
	m_PropUILink = nullptr;
	m_关联组件 = nullptr;
}

C_Widget::~C_Widget() {
	f_移除画布();
	
	m_键位映射.clear();

	uint32 num = m_子组件.size();
	auto data = m_子组件.data();
	for (uint32 i = 0; i < num; ++i) {
		delete data[i];
	}
	m_子组件.clear();
}

void C_Widget::f_setPos(vec2 pos) {
	if (m_Pos != pos) {
		m_Pos = pos;

		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		f_widget_更新绘制(this);
	}
}
void C_Widget::f_setSize(vec2 size) {
	if (m_Size != size) {
		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		f_widget_更新绘制(this);

		m_Size = size;
	}
}

void C_Widget::f_setOriginalPos(vec2 pos) {
	//m_更新绘制属性 = true;
	f_widget_更新绘制(this);

	m_Pos = pos;
	m_OriginalPos = m_Pos;
}
void C_Widget::f_setOriginalSize(vec2 size) {
	//m_更新绘制属性 = true;
	f_widget_更新绘制(this);

	m_Size = size;
	m_OriginalSize = size;
}
void C_Widget::f_setMinSize(vec2 size) {
	//m_更新绘制属性 = true;
	f_widget_更新绘制(this);

	m_Size = m_Scale * size;
	m_MinSize = m_Scale * size;
	m_OriginalSize = size;
}





void C_Widget::f_setX(float32 x) {
	if (m_Pos.x != x) {
		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		f_widget_更新绘制(this);
		m_Pos.x = x;
	}
}

void C_Widget::f_setY(float32 y) {
	if (m_Pos.y != y) {
		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		f_widget_更新绘制(this);
		m_Pos.y = y;
	}
}

void C_Widget::f_setW(float32 w) {
	if (m_Size.x != w) {
		f_widget_更新绘制(this);
		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		m_Size.x = w;
		m_OriginalSize.x = w;
	}
}

void C_Widget::f_setH(float32 h) {
	if (m_Size.y != h) {
		f_widget_更新绘制(this);
		//m_更新绘制属性 = true;
		//m_更新下层绘制 = true;
		m_Size.y = h;
	}
}



vec2 C_Widget::f_getPos() const {
	return m_Pos;
}
vec2 C_Widget::f_getSize() const {
	return m_Size;
}
vec2 C_Widget::f_getOriginalPos() const {
	return m_OriginalPos;
}
vec2 C_Widget::f_getOriginalSize() const {
	return m_OriginalSize;
}




C_Widget管理* C_Widget::f_get窗口管理() {
	if (m_UIctx) {
		return m_UIctx->m_GM;
	}
	return m_GM;
}

S_需更新部件 C_Widget::f_get更新组件() {
	return { m_子组件.data(), uint32(m_子组件.size()) };
}

C_Widget* C_Widget::f_get子组件(uint32 id) {
	if (id < m_子组件.size()) {
		return m_子组件[id];
	}
	return nullptr;
}

void C_Widget::f_裁剪() {
	
	uint32 num = m_子组件.size();
	if (!num) return;
	auto p = m_子组件.data();

	vec4* arec = m_使用父组件裁剪 ? &(m_父部件->m_裁剪大小) : &m_裁剪大小;

	uint32 拆分次数 = num / 8;
	uint32 多出次数 = num - 拆分次数*8;

	for (uint32 i = 0; i < 拆分次数; ++i) {
		f_widget_裁剪组件_avx(m_GlobalLoc, *arec, &(p[i*8]), 8);
	}
	if (多出次数) {
		f_widget_裁剪组件_avx(m_GlobalLoc, *arec, &(p[拆分次数 * 8]), 多出次数);
	}
}


void f_widget_裁剪组件(const vec2& 父组件全局位置, const vec4& 裁剪area, C_Widget* w) {
	w->m_GlobalLoc = 父组件全局位置 + w->m_Pos;

	float32 左边, 顶边, 右边, 底边;
	左边 = w->m_GlobalLoc.x;
	顶边 = w->m_GlobalLoc.y;
	右边 = w->m_Size.x;
	底边 = w->m_Size.y;

	右边 = 左边 + 右边;
	底边 = 顶边 + 底边;

	左边 = DEF_Max(左边, 裁剪area.x);
	右边 = DEF_Min(右边, 裁剪area.z);
	顶边 = DEF_Max(顶边, 裁剪area.y);
	底边 = DEF_Min(底边, 裁剪area.w);

	w->m_被裁剪 = false;
	if (左边 > 裁剪area.z || 顶边 > 裁剪area.w) {
		w->m_被裁剪 = true;
	}
	if (右边 < 裁剪area.x || 底边 < 裁剪area.y) {
		w->m_被裁剪 = true;
	}
	if (w->m_被裁剪 == false) {
		w->m_裁剪大小.x = 左边;
		w->m_裁剪大小.y = 顶边;
		w->m_裁剪大小.z = 右边;
		w->m_裁剪大小.w = 底边;
	}
}





void f_widget_裁剪组件_avx(const vec2& pos, const vec4& 裁剪area, C_Widget** ws, uint8 num) {
	//__m128 a = _mm_add_ps(m_area, area);
	auto 父级左边 = _mm256_set1_ps(裁剪area.x);
	auto 父级顶边 = _mm256_set1_ps(裁剪area.y);
	auto 父级右边 = _mm256_set1_ps(裁剪area.z);
	auto 父级底边 = _mm256_set1_ps(裁剪area.w);


	__m256 左边;
	__m256 顶边;
	__m256 右边;
	__m256 底边;

	for (uint32 i = 0; i < num; ++i) {
		ws[i]->m_GlobalLoc = pos + ws[i]->m_Pos;
		//ws[i]->m_GlobalLoc.x = pos.x + ws[i]->m_Pos.x;
		//ws[i]->m_GlobalLoc.y = pos.y + ws[i]->m_Pos.y;
		左边.m256_f32[i] = ws[i]->m_GlobalLoc.x;
		顶边.m256_f32[i] = ws[i]->m_GlobalLoc.y;

		右边.m256_f32[i] = ws[i]->m_Size.x;
		底边.m256_f32[i] = ws[i]->m_Size.y;
	}

	右边 = _mm256_add_ps(左边, 右边);
	底边 = _mm256_add_ps(顶边, 底边);


	左边 = _mm256_max_ps(左边, 父级左边);
	右边 = _mm256_min_ps(右边, 父级右边);

	顶边 = _mm256_max_ps(顶边, 父级顶边);
	底边 = _mm256_min_ps(底边, 父级底边);



	//auto 是否大于左边 = _mm256_cmp_ps(左边, 父级右边, _CMP_GE_OS);
	//auto 是否大于底边 = _mm256_cmp_ps(顶边, 父级底边, _CMP_LE_OQ);
	//左边大于父组件右边 或 顶边大于父组件底边
	auto H是否重叠 = _mm256_and_ps(_mm256_cmp_ps(左边, 父级右边, _CMP_GT_OS), _mm256_cmp_ps(顶边, 父级底边, _CMP_GT_OS));
	//右边是否小于父部件坐标 或 底边是否小于父布局顶边
	auto V是否重叠 = _mm256_and_ps(_mm256_cmp_ps(右边, 父级左边, _CMP_LT_OQ), _mm256_cmp_ps(底边, 父级顶边, _CMP_LT_OQ));
	H是否重叠 = _mm256_or_ps(H是否重叠, V是否重叠);

	auto 同轴向逆向H = _mm256_cmp_ps(右边, 左边, _CMP_LT_OQ);
	auto 同轴向逆向V = _mm256_cmp_ps(底边, 顶边, _CMP_LT_OQ);
	H是否重叠 = _mm256_or_ps(H是否重叠, 同轴向逆向H);
	H是否重叠 = _mm256_or_ps(H是否重叠, 同轴向逆向V);



	for (uint32 i = 0; i < num; ++i) {
		if (H是否重叠.m256_f32[i]) {
			ws[i]->m_被裁剪 = true;
			
		}
		else {
			ws[i]->m_被裁剪 = false;
			ws[i]->m_裁剪大小.x = 左边.m256_f32[i];
			ws[i]->m_裁剪大小.y = 顶边.m256_f32[i];
			ws[i]->m_裁剪大小.z = 右边.m256_f32[i];
			ws[i]->m_裁剪大小.w = 底边.m256_f32[i];

		}
	}
}

void f_widget_单个部件裁剪(C_Widget* w, const vec4& 父area, const vec2& 父全局坐标) {
	w->m_GlobalLoc = 父全局坐标 + w->m_Pos;

	vec2 右边底边 = w->m_GlobalLoc + w->m_Size;

	w->m_裁剪大小.x = DEF_Max(w->m_GlobalLoc.x, 父area.x);
	w->m_裁剪大小.z = DEF_Min(右边底边.x, 父area.z);

	w->m_裁剪大小.y = DEF_Max(w->m_GlobalLoc.y, 父area.y);
	w->m_裁剪大小.w = DEF_Min(右边底边.y, 父area.w);


	if (w->m_裁剪大小.x >= 父area.z || w->m_裁剪大小.y >= 父area.w) {
		w->m_被裁剪 = true;
	}
	if (w->m_裁剪大小.z <= 父area.x || w->m_裁剪大小.w <= 父area.y) {
		w->m_被裁剪 = true;
	}

	w->m_被裁剪 = false;
}

int8 f_widget_筛选焦点组件_avx(C_Widget** ws, uint8 num, const vec2& point) {
	auto 鼠标X = _mm256_set1_ps(point.x);
	auto 鼠标Y = _mm256_set1_ps(point.y);

	__m256 左边 = _mm256_set1_ps(0.0);
	__m256 顶边 = _mm256_set1_ps(0.0);
	__m256 右边 = _mm256_set1_ps(0.0);
	__m256 底边 = _mm256_set1_ps(0.0);

	for (uint32 i = 0; i < num; ++i) {
		左边.m256_f32[i] = ws[i]->m_裁剪大小.x;
		顶边.m256_f32[i] = ws[i]->m_裁剪大小.y;
		右边.m256_f32[i] = ws[i]->m_裁剪大小.z;
		底边.m256_f32[i] = ws[i]->m_裁剪大小.w;
	}

	//_mm256_cmp_ps(鼠标X, 右边, _CMP_LT_OQ);
	//_mm256_cmp_ps(鼠标Y, 底边, _CMP_LT_OQ);
	auto 
	在范围 = _mm256_and_ps(_mm256_cmp_ps(鼠标X, 左边, _CMP_GT_OS), _mm256_cmp_ps(鼠标Y, 顶边, _CMP_GT_OS));
	在范围 = _mm256_and_ps(_mm256_cmp_ps(鼠标X, 右边, _CMP_LT_OQ), 在范围);
	在范围 = _mm256_and_ps(_mm256_cmp_ps(鼠标Y, 底边, _CMP_LT_OQ), 在范围);

	for (uint32 i = 0; i < num; ++i) {
		if (在范围.m256_f32[i]) {
			return i;
		}
	}

	return -1;
}

bool f_widget_点是否在组件内(C_Widget* w, const vec2& point) {
	if (point.x >= w->m_GlobalLoc.x && point.y >= w->m_GlobalLoc.y) {
		auto rect = w->f_getRect(true);

		rect.extent += w->m_GlobalLoc;
		if (point < rect.extent) {
			return true;
		}
	}

	return false;
}


static std::vector<S_部件添加列队> g待添加部件;
static std::vector<C_Widget*> g待销毁部件;

void f_widget_销毁子部件(C_Widget* self, int32 offset, int32 num, bool 即时销毁) {
	std::vector<C_Widget*> 要销毁的组件;
	for (int32 i = 0; i < num; ++i) {
		要销毁的组件.push_back(self->m_子组件[i + offset]);
	}
	self->m_子组件.erase(self->m_子组件.begin() + offset, self->m_子组件.begin() + offset + num);

	if (即时销毁 == false) {
		for (auto& e : 要销毁的组件) {
			delete e;
		}
	}
	else {
		f_widget_push待销毁部件(要销毁的组件.data(), 要销毁的组件.size());
	}
}

void f_widget_remove区间子组件(C_Widget* self, int32 s, int32 e, bool 即时销毁) {
	if(e < 0) e = self->m_子组件.size();

	std::vector<C_Widget*> 要销毁的组件;
	for (int32 i = s; i < e; ++i) {
		要销毁的组件.push_back(self->m_子组件[i]);
	}
	
	if (要销毁的组件.size()) {
		f_widget_push待销毁部件(要销毁的组件.data(), 要销毁的组件.size());

		self->m_子组件.erase(self->m_子组件.begin() + s, self->m_子组件.begin() + e);
		self->m_更新绘制属性 = true;
	}
}

void f_widget_remove子部件(C_Widget* self, uint32* id, uint32 num, bool 即时销毁) {
	std::vector<C_Widget*>	删除部件(num);
	auto* 子部件	= self->m_子组件.data();
	uint32 末尾ID = self->m_子组件.size();

	auto* data = 删除部件.data();

	for (uint32 i = 0; i < num; ++i) {
		--末尾ID;

		uint32 cid = id[i];

		bool 是否交换 = true;
		for (uint32 j = 0; j < num; ++j) {
			if (末尾ID == id[j]) {
				是否交换 = false;
				break;
			}
		}
		data[i] = 子部件[cid];;

		if (是否交换) {
			子部件[cid] = 子部件[末尾ID];
			子部件[cid]->m_实例ID = data[i]->m_实例ID;
		}
	}

	self->m_子组件.erase(self->m_子组件.begin() + 末尾ID, self->m_子组件.end());
	if(即时销毁) f_widget_push待销毁部件(data, num);
}

void f_widget_remove子部件(C_Widget* self, std::vector<C_Widget*>& ws, bool 即时销毁) {
	for (auto it = self->m_子组件.begin(); ; ) {
		if (it == self->m_子组件.end()) {
			break;
		}

		bool 推进 = true;
		for (auto e : ws) {
			if (*it == e) {
				it = self->m_子组件.erase(it);
				推进 = false;
				break;
			}
		}
		
		if(推进) 
			++it;
	}

	if (即时销毁) {
		f_widget_push待销毁部件(ws.data(), ws.size());
	}
}


void f_widget_remove所有子部件(C_Widget* self, bool 即时销毁) {
	if (即时销毁) {
		for (auto& e : self->m_子组件) {
			delete e;
		}
	}
	else {
		f_widget_push待销毁部件(self->m_子组件.data(), self->m_子组件.size());
	}
	self->m_子组件.clear();
	self->m_更新绘制属性 = true;
}


void f_widget_push待销毁部件(C_Widget** ws, uint32 num) {
	for (uint32 i = 0; i < num; ++i) {
		g待销毁部件.push_back(ws[i]);
	}
}


static void f_widget_扁平化组件(C_Widget* w, std::vector<C_Widget*>& r) {
	r.insert(r.end(), w->m_子组件.begin(), w->m_子组件.end());

	for (auto& e : w->m_子组件) {
		f_widget_扁平化组件(e, r);
	}
}


void f_widget_动态销毁UI部件(C_Widget管理* gm) {
	
	std::vector<C_Widget*> 扁平化组件;
	for (auto& e : g待销毁部件) {
		扁平化组件.push_back(e);
		f_widget_扁平化组件(e, 扁平化组件);
	}
	
	uint32 num = 扁平化组件.size();
	//gm->f_裁剪层();
	if (num) {
		for (int8 焦点组件ID = 0; 焦点组件ID < gm->m_上一次焦点组件数量; ++焦点组件ID) {
			for (uint32 i = 0; i < num; ++i) {
				if (gm->m_上一次焦点组件[焦点组件ID] == 扁平化组件[i]) {
					gm->m_上一次焦点组件[焦点组件ID] = nullptr;
					break;
				}
			}
		}


		auto it = std::find(扁平化组件.begin(), 扁平化组件.end(), gm->m_当前拖拽部件);
		if (it != 扁平化组件.end()) {
			gm->m_当前拖拽部件 = nullptr;
		}
		it = std::find(扁平化组件.begin(), 扁平化组件.end(), gm->m_当前操作部件);
		if (it != 扁平化组件.end()) {
			gm->m_当前操作部件 = nullptr;
		}
	}



	num = g待销毁部件.size();
	for (uint32 i = 0; i < num; ++i) {
		delete g待销毁部件[i];
	}
	g待销毁部件.clear();

	if (num) {
		gm->m_当前拖拽部件 = nullptr;
	}
}




void f_widget_push待添加部件(C_Widget* r, C_Widget** ws, uint32 num, int32 offset, bool 即时执行) {
	for (uint32 i = 0; i < num; ++i) {
		f_widget_push待添加部件(r, ws[i], i + offset, 即时执行);
	}
}

void f_widget_push待添加部件(C_Widget* r, C_Widget* ws, int32 loc, bool 即时执行) {
	g待添加部件.push_back({ r, ws, loc });
	
	if (即时执行) {
		f_widget_执行待添加部件();
	}
}

void f_widget_执行待添加部件() {
	uint32 num = g待添加部件.size();

	for (uint32 i = 0; i < num; ++i) {
		auto& e = g待添加部件[i];

		e.m_rW->f_添加子组件(e.m_aW, e.m_Loc);
	}
	g待添加部件.clear();
}

void f_widget_添加子组件(C_Widget* self, const std::vector<C_Widget*>& ws) {
	auto* wp = ws.data();
	uint32 num = ws.size();
	
	for (uint32 i = 0; i < num; ++i) {
		self->f_添加子组件(wp[i]);
	}
}

void f_widget_set子组件(C_Widget* self, C_Widget* s, int32 loc) {
	self->m_子组件[loc] = s;
	s->m_父部件 = self;
}

void f_widget_关联组件(C_Widget* r, C_Widget* s) {
	if (r->m_关联组件 == nullptr) {
		r->m_关联组件 = (S_关联组件*)malloc(sizeof(S_关联组件));
		r->m_关联组件->m_W = r;
	}

	s->m_关联组件 = r->m_关联组件;
}






//void f_widget_draw(S_2D画布& 画布) {
//	for(auto& e : 画布.m_绘制元素) f_surface2D_release(e);
//	画布.m_绘制元素.clear();
//}



void C_Widget::f_绘图() {
	
	if (m_画布 && m_画布->m_是否重绘 && mf_绘制) {
		for(auto& e : m_画布->m_绘制元素) f_surface2D_release(e);
		m_画布->m_绘制元素.clear();

		mf_绘制(this, m_画布);
		m_画布->m_是否重绘 = false;
	}

	uint32 sonNum = m_子组件.size();
	auto* p = m_子组件.data();
	for (uint32 i = 0; i < sonNum; ++i) {
		p[i]->f_绘图();
	}
}

void C_Widget::f_添加子组件(C_Widget* w, int32 loc) {
	
	if (loc > m_子组件.size() || loc < 0) {
		m_子组件.push_back(w);
	}
	else {
		auto it = m_子组件.begin() + loc;
		m_子组件.insert(it, w);
	}

	//if (w->m_区域帧缓存根 == nullptr) {
	//	w->m_区域帧缓存根 = m_区域帧缓存根;
	//}

	//if (w->m_画布) {
	//	w->m_渲染层 = w->m_UIctx->m_GM->f_添加渲染组件(w->m_渲染层, w);
	//}


	w->m_父部件 = this;
	w->m_UIctx = m_UIctx;

	m_更新绘制属性 = true;
}

void C_Widget::f_销毁子组件(int32 id) {
	C_Widget* data[1];
	if (id >= m_子组件.size()) {
		data[0] = m_子组件.back();
		m_子组件.pop_back();
	} 
	else {
		data[0] = m_子组件[id];
		m_子组件.erase(m_子组件.begin()+id);
	}
	f_widget_push待销毁部件(data, 1);

	//if (data[0]->m_画布) {
	//	data[0]->m_UIctx->m_GM->f_移除渲染组件(data[0]->m_渲染层, data[0]);
	//}
	m_更新绘制属性 = true;
}

void C_Widget::f_替换子组件(int32 id, C_Widget* w) {
	w->m_GlobalLoc = m_子组件[id]->m_GlobalLoc;
	w->m_裁剪大小 = m_子组件[id]->m_裁剪大小;
	w->m_Size = m_子组件[id]->m_Size;
	w->m_Pos = m_子组件[id]->m_Pos;

	w->m_区域帧缓存根 = m_子组件[id]->m_区域帧缓存根;
	w->m_区域链接根 = m_子组件[id]->m_区域链接根;
	w->m_渲染层 = m_子组件[id]->m_渲染层;

	m_子组件[id] = w;

	w->m_父部件		= this;
	m_更新绘制属性	= true;
}

void C_Widget::f_置裁剪(bool 裁剪) {
	m_被裁剪 = 裁剪;
	for (auto& e : m_子组件) {
		e->f_置裁剪(裁剪);
	}
}

void C_Widget::f_置显示(bool 显示) {
	m_显示 = 显示;
	m_开启渲染 = 显示;

	//if (m_画布 && m_UIctx) {
	//	if (显示) {
	//		m_渲染层 = m_UIctx->m_GM->f_添加渲染层(m_渲染层, this);
	//	}
	//	else {
	//		m_UIctx->m_GM->f_移除渲染层(m_渲染层, this);
	//	}
	//}

	for (auto& e : m_子组件) {
		e->f_置显示(显示);
	}
}

void C_Widget::f_绑定窗口管理(C_Widget管理* gm) {
	m_GM = gm;
}

void C_Widget::f_添加画布(S_2D画布* 引用画布) {
	if (引用画布) {
		m_画布 = 引用画布;
		m_引用画布 = true;
	}
	else if(!m_画布) {
		m_画布 = f_surface_创建2D画布(0, m_UIctx->m_Ctx);
	}
	assert(m_画布);
}

void C_Widget::f_移除画布() {
	//if(m_UIctx) m_UIctx->m_GM->f_移除渲染组件(this, m_渲染层);

	if (m_画布 && !m_引用画布) {
		f_surface_释放2D画布(m_画布);
	}
	m_画布 = nullptr;
}

//void C_Widget::f_置子组件绘制根区域为当前组件() {
//	for (auto& e : m_子组件) {
//		e->m_区域帧缓存根 = this;
//	}
//}




S_UI渲染区域::S_UI渲染区域()
{
	
}

S_UI渲染区域::~S_UI渲染区域() {
	
}

void S_UI渲染区域::f_设置层分辨率(S_设备环境& ctx, uvec2 分辨率, uvec2 模糊纹理分辨率) {
	
}



inline S_UI渲染层::S_UI渲染层(S_UI渲染环境& uiCtx, uvec2 纹理大小):
	m_顶层(false),
	m_更新(false),
	m_帧累计(0)
{
	uvec3 纹理大小3 = { 纹理大小.x, 纹理大小.y, 1 };

	S_纹理* 叠加纹理 = f_tex_创建帧缓存图像(uiCtx.m_Ctx, 纹理大小3, E_纹理格式::e_tf_RGBA8U_归一化, E_MS次数::e_MS_1);
	f_tex_安装纹理采样器(叠加纹理, S_全局缓存::g_默认采样器);
	f_tex_读写布局(叠加纹理);
	m_叠加纹理 = 叠加纹理;

	

	纹理大小3 = 纹理大小3 >> 2;
	纹理大小3 /= 16;
	纹理大小3 *= 16;
	纹理大小3 += 16;

	S_纹理* 模糊纹理 = f_tex_创建帧缓存图像(uiCtx.m_Ctx, 纹理大小3, E_纹理格式::e_tf_RGBA8U_归一化, E_MS次数::e_MS_1);
	f_tex_安装纹理采样器(模糊纹理, uiCtx.m_Ctx.m_几何图形->m_UI模糊采样器);
	f_tex_读写布局(模糊纹理);
	m_模糊纹理 = 模糊纹理;

	//m_合成层 = f_vg_genComposition(uiCtx.m_Ctx, *uiCtx.m_合成画布, E_图层混合模式::e_Normal);

}

inline S_UI渲染层::~S_UI渲染层() {
	f_tex_销毁纹理(m_叠加纹理);
	f_tex_销毁纹理(m_模糊纹理);
	
	f_surface_销毁平面帧(m_sruface);
	//f_surface2D_release(m_合成层);
}


bool S_UI渲染层::f_添加绘制区域(C_Widget* key, C_Widget* w) {
	if (m_渲染区域.find(key) == m_渲染区域.end()) {
		auto& e = m_渲染区域[key];
		e.m_重排序 = true;

		if (w) {
			e.m_渲染组件.push_back(w);
		}

		m_帧累计 = 0;
		m_更新 = true;
		return true;
	}
	else {
		return false;
	}
	
	//if (e.m_渲染组件迭代器.find(w) == e.m_渲染组件迭代器.end()) {
	//	e.m_渲染组件迭代器[w] = e.m_渲染组件.end();
	//
	//	e.m_渲染组件.push_front(w);
	//	e.m_渲染组件迭代器[w] = e.m_渲染组件.begin();
	//	
	//
	//	w->m_更新绘制属性 = true;
	//}
}

bool S_UI渲染层::f_移除绘制区域(C_Widget* key, C_Widget* w) {
	m_渲染区域.erase(key);
	
	return m_渲染区域.size();
	//if (e.m_渲染组件迭代器.find(w) != e.m_渲染组件迭代器.end()) {
	//	auto it = e.m_渲染组件迭代器[w];
	//
	//	e.m_渲染组件.erase(it);
	//	e.m_渲染组件迭代器.erase(w);
	//	
	//}
	//return e.m_渲染组件迭代器.size();
}

void S_UI渲染层::f_替换绘制区域(C_Widget* key, C_Widget* w, C_Widget* 原组件) {
	//assert(key);

	f_移除绘制区域(key, 原组件);
	f_添加绘制区域(key, w);

	auto& e = m_渲染区域[key];

	return;
	//if (e.m_渲染组件迭代器.find(原组件) != e.m_渲染组件迭代器.end()) {
	//	
	//}
}

void S_UI渲染层::f_插入绘制组件(C_Widget* key, C_Widget* w, C_Widget* 上层组件) {
	//assert(key);
	auto& e = m_渲染区域[key];

	return;
	//if (e.m_渲染组件迭代器.find(上层组件) != e.m_渲染组件迭代器.end()) {
	//	auto it = e.m_渲染组件迭代器[上层组件];
	//	it = std::next(it);
	//
	//	it = e.m_渲染组件.insert(it, w);
	//	e.m_渲染组件迭代器[w] = it;
	//}
	//else {
	//	f_添加绘制区域(key, w);
	//}
}

void S_UI渲染层::f_清除绘制组件() {
	for (auto& e : m_渲染区域) {
		e.second.m_渲染组件.clear();
		//e.second.m_渲染组件迭代器.clear();
	}
	m_渲染区域.clear();
}

void S_UI渲染层::f_设置层分辨率(S_设备环境& ctx, uvec2 分辨率, uvec2 模糊纹理分辨率) {
	//for (auto& e : m_渲染区域) {
	//	f_tex_修改大小(m_叠加纹理, _uVec3(分辨率, 1), false);
	//	f_tex_修改大小(m_模糊纹理, _uVec3(模糊纹理分辨率, 1), false);
	//}
	//e.f_设置层分辨率(ctx, 分辨率, 模糊纹理分辨率);

	f_surface_重置平面帧大小(ctx, m_sruface, 分辨率);

	f_tex_修改大小(m_叠加纹理, _uVec3(分辨率, 1), false);
	f_tex_修改大小(m_模糊纹理, _uVec3(模糊纹理分辨率, 1), false);
}



C_渲染层分配::C_渲染层分配(uint32 layer) {
	m_层ID = layer;
}

C_渲染层分配 C_渲染层分配::f_下一层() {
	return C_渲染层分配(m_层ID + 1);
}

void C_渲染层分配::f_置组件渲染层(C_Widget* w) {
	w->m_渲染层 = m_层ID;
	w->m_区域帧缓存根 = w;

	auto* gm = w->f_get窗口管理();
	if (gm->m_顶层渲染层 <= w->m_渲染层) {
		gm->m_顶层渲染层 = w->m_渲染层 + 1;
	}

	gm->f_添加渲染层(w->m_渲染层, w);
}

void C_渲染层分配::f_移除渲染层组件(C_Widget* w) {
	auto* gm = w->f_get窗口管理();
	gm->f_移除渲染层(w->m_渲染层, w);
}

void C_渲染层分配::f_替换渲染层组件(C_Widget * w, C_Widget * old) {
	auto* gm = w->f_get窗口管理();
	gm->f_移除渲染层(w->m_渲染层, old);
	f_置组件渲染层(w);
}







C_Widget管理::C_Widget管理(S_UI渲染环境& ctx): 
	m_UICtx(&ctx) ,
	m_Window(nullptr),
	m_渲染参数({}), m_顶层渲染层(1),

	m_下层组件拾取计数(0), m_弹出层组件拾取计数(0),

	mf_输入执行前回调(f_部件更新阶段回调), mf_输入执行后回调(f_部件更新阶段回调),
	有输入事件(false), m_当前拖拽部件(nullptr), m_当前操作部件(nullptr), 
	
	m_当前独占操作文本框(nullptr), m_当前文本输入框(nullptr)
{
	m_投影矩阵 = f_buf_create板载缓存(m_UICtx->m_Ctx, sizeof(Mat44f) * 2, E_板载缓存类型::e_UBO);
	m_采样属性 = f_buf_create板载缓存(m_UICtx->m_Ctx, sizeof(S_FrameSample_TAA), E_板载缓存类型::e_UBO, DEF_UI_LayerNum);
	
	memset(&m_帧采样属性, 0, sizeof(S_FrameSample_TAA) * DEF_UI_LayerNum);
	f_buf_fill(m_采样属性, 0, &m_帧采样属性, DEF_UI_LayerNum);
	
	//m_视口GPU参数设置 = f_gpu_创建参数布局(m_投影矩阵, 0, E_着色阶段::e_顶点着色 | E_着色阶段::e_几何着色 | E_着色阶段::e_像素着色 | E_着色阶段::e_计算着色);
	
	for (uint8 k = 0; k < 8; ++k) {
		鼠标按键状态[k] = DEF_按键状态_准备;
	}
	拖放状态 = DEF_拖放状态_准备;


	m_上一次焦点组件数量 = 0;
	for (uint8 i = 0; i < 128; ++i) {
		m_上一次焦点组件[i] = nullptr;
		m_焦点组件[i] = nullptr;
	}

	

	视口.x = 0;
	视口.y = 0;
	视口.width = 1024;
	视口.height = 576;
	视口.minDepth = 0;
	视口.maxDepth = 1;

	m_模糊纹理大小 = _uVec2(视口.width, 视口.height) >> 2;
	m_模糊纹理大小 /= 16;
	m_模糊纹理大小 *= 16;
	m_模糊纹理大小 += 16;

	


	const uint32 纹理数组数量 = (DEF_UI_LayerNum + 1) * 3;

	m_合成采样纹理集 = f_纹理集_创建(纹理数组数量);
	m_合成写入纹理集 = f_纹理集_创建(纹理数组数量);

	m_模糊采样纹理集 = f_纹理集_创建(纹理数组数量);
	m_模糊写入纹理集 = f_纹理集_创建(纹理数组数量);


	std::vector<S_纹理*> 填充纹理(纹理数组数量, S_全局缓存::g_空纹理);
	f_纹理集_fill纹理(m_合成采样纹理集, 填充纹理);
	f_纹理集_fill纹理(m_合成写入纹理集, 填充纹理);

	f_纹理集_fill纹理(m_模糊采样纹理集, 填充纹理);
	f_纹理集_fill纹理(m_模糊写入纹理集, 填充纹理);


	

	m_合成纹理绑定槽 = f_纹理槽_创建(2);
	m_图层累积 = f_创建线管_UI累计合成(m_UICtx->m_Ctx);
	m_图层模糊 = f_创建线管_UI图层模糊(m_UICtx->m_Ctx);
	
	m_DS_累积 = new C_VkDescriptorSet(m_图层累积->m_Pipeline, m_图层累积->m_Shader);
	m_DS_模糊 = new C_VkDescriptorSet(m_图层模糊->m_Pipeline, m_图层模糊->m_Shader);
	f_df_创建常量推送<S_ConstPush_TAA>(m_合成常量参数, E_着色阶段::e_计算着色);
	


	m_文本编辑框画布 = f_surface_创建2D画布(0, m_UICtx->m_Ctx);
	f_绘制编辑框文本编辑();
}

C_Widget管理::~C_Widget管理() {
	for (auto& e : m_渲染层垃圾回收) {
		delete e;
	}
	//f_surface_销毁平面帧(m_sruface);

	for (auto& e : m_帧渲染层) {
		delete e;
	}

	f_纹理集_销毁(m_合成采样纹理集);

	f_df_销毁常量推送(m_合成常量参数);

	delete m_DS_累积;
	delete m_DS_模糊;
}

void C_Widget管理::f_重置事件() {
	m_当前拖拽部件 = nullptr;
	m_当前操作部件 = nullptr;

	m_上一次焦点组件数量 = 0;
	m_焦点数量 = 0;

}

inline uint32 C_Widget管理::f_添加渲染层(uint32 绘图层, C_Widget* key) {
	assert(绘图层 < DEF_UI_LayerNum);

	uint32 新层 = 绘图层;
	for (uint32 i = m_帧渲染层.size(); i <= 新层; ++i) {
		S_UI渲染层* UI渲染层;
		
		if (m_渲染层垃圾回收.size()) {
			UI渲染层 = m_渲染层垃圾回收.back();
			m_渲染层垃圾回收.pop_back();

			UI渲染层->f_设置层分辨率(m_UICtx->m_Ctx, _uVec2(视口.width, 视口.height), m_模糊纹理大小);
		}
		else {
			auto 纹理大小 = _uVec2(视口.width, 视口.height);
			UI渲染层 = new S_UI渲染层(*(key->m_UIctx), 纹理大小);

			UI渲染层->m_sruface = f_surface_创建平面帧(m_UICtx->m_Ctx, _uVec2(视口.width, 视口.height));
			UI渲染层->m_sruface->m_帧缓存->m_清除颜色 = { 0,0,0,0 };
		}


		f_纹理集_set纹理(m_合成写入纹理集, UI渲染层->m_叠加纹理,	i);
		f_纹理集_set纹理(m_模糊写入纹理集, UI渲染层->m_模糊纹理,	i);

		f_纹理集_set纹理(m_合成采样纹理集, UI渲染层->m_模糊纹理,	(i + 0) * 3);
		f_纹理集_set纹理(m_合成采样纹理集, UI渲染层->m_sruface->m_Color[0],	i * 3 + 1);
		f_纹理集_set纹理(m_合成采样纹理集, UI渲染层->m_sruface->m_Color[1],	i * 3 + 2);
		
		f_纹理集_set纹理(m_模糊采样纹理集, UI渲染层->m_sruface->m_Color[0],	i * 2 + 0);
		f_纹理集_set纹理(m_模糊采样纹理集, UI渲染层->m_sruface->m_Color[1],	i * 2 + 1);
		
		m_帧渲染层.emplace_back(UI渲染层);
	}

	if (m_帧渲染层[绘图层]->f_添加绘制区域(key, nullptr)) {
		auto& e = m_帧渲染层[绘图层]->m_渲染区域[key];
		e.m_所属层 = 绘图层;
	}

	//f_更新层(绘图层);
	return 绘图层;
}

inline void C_Widget管理::f_移除渲染层(uint32 绘图层, C_Widget* w) {
	if (绘图层 >= m_帧渲染层.size() || !w->m_区域帧缓存根) return;

	auto& e = m_帧渲染层[绘图层];
	if (e->f_移除绘制区域(w->m_区域帧缓存根, w) == false ) {
		//f_纹理集_set纹理(m_合成写入纹理集, S_全局缓存::g_空纹理, 绘图层);
		//f_纹理集_set纹理(m_模糊写入纹理集, S_全局缓存::g_空纹理, 绘图层);
		//
		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, (绘图层 + 1) * 3);
		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, 绘图层 * 3 + 1);
		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, 绘图层 * 3 + 2);
		//
		//f_纹理集_set纹理(m_模糊采样纹理集, S_全局缓存::g_空纹理, 绘图层 * 2 + 0);
		//f_纹理集_set纹理(m_模糊采样纹理集, S_全局缓存::g_空纹理, 绘图层 * 2 + 1);
		//
		//m_渲染层垃圾回收.push_back(e);
		//m_帧渲染层.erase(m_帧渲染层.begin() + 绘图层);
		
		//if (e->m_渲染区域[w->m_区域帧缓存根].m_渲染组件.size()) {
		//	m_帧渲染层.erase(m_帧渲染层.begin() + 绘图层);
		//}
	}
}

Inline void f_取绘制组件(C_Widget* w, std::vector<C_Widget*>& 组件迭代栈) {
	w->m_更新绘制属性 = true;
	if (w->m_画布) {
		组件迭代栈.emplace_back(w);
	}
	for(auto& e : w->m_子组件) f_取绘制组件(e, 组件迭代栈);
}

inline void C_Widget管理::f_替换绘制层(uint32 绘图层, C_Widget* w, C_Widget* 原组件) {
	if (m_帧渲染层.size() <= 绘图层) return;

	auto& 层 = m_帧渲染层[绘图层];

	std::vector<C_Widget*> 组件迭代栈;
	f_取绘制组件(原组件, 组件迭代栈);
	for (auto& e : 组件迭代栈) {
		层->f_移除绘制区域(e->m_区域帧缓存根, e);
	}

	组件迭代栈.clear();
	f_取绘制组件(w, 组件迭代栈);
	for (auto& e : 组件迭代栈) {
		层->f_添加绘制区域(e->m_区域帧缓存根, e);
	}
	
}

inline void C_Widget管理::f_插入绘制层(uint32 绘图层, C_Widget* w, C_Widget* 上层组件) {
	if (绘图层 < m_帧渲染层.size()) {
		m_帧渲染层[绘图层]->f_插入绘制组件(w->m_区域帧缓存根, w, 上层组件);
	}
	else {
		f_添加渲染层(绘图层, w);
	}
}

void C_Widget管理::f_裁剪层(uint32 开始层) {
	uint32 num = m_帧渲染层.size();

	for (uint32 i = 开始层; i < num; ++i) {
		auto& e = m_帧渲染层[i];

		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, i * 3);
		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, i * 3 + 1);
		//f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, i * 3 + 2);

		f_纹理集_set纹理(m_合成写入纹理集, S_全局缓存::g_空纹理, i);
		f_纹理集_set纹理(m_模糊写入纹理集, S_全局缓存::g_空纹理, i);


		f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, (i + 1) * 3);
		f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, i * 3 + 1);
		f_纹理集_set纹理(m_合成采样纹理集, S_全局缓存::g_空纹理, i * 3 + 2);

		f_纹理集_set纹理(m_模糊采样纹理集, S_全局缓存::g_空纹理, i * 2 + 0);
		f_纹理集_set纹理(m_模糊采样纹理集, S_全局缓存::g_空纹理, i * 2 + 1);

		e->f_清除绘制组件();
		m_渲染层垃圾回收.emplace_back(e);
	}

	m_帧渲染层.resize(开始层);
}

void C_Widget管理::f_记录裁剪层(uint32 开始层) {
	m_异步裁剪层记录.insert(开始层);
}

void C_Widget管理::f_裁剪层() {
	for (auto i : m_异步裁剪层记录) {
		f_裁剪层(i);
	}
	m_异步裁剪层记录.clear();
}

void C_Widget管理::f_更新层(uint32 层) {
	//for (uint32 i = 层; i < m_帧渲染层.size(); ++i) {
	//	m_帧渲染层[i]->m_帧累计 = 0;
	//}
	if (层 < m_帧渲染层.size()) {
		//m_帧渲染层[层]->m_帧累计 = 0;
	}
	
	//m_帧渲染层[层]->m_帧累计 = 0;
}

void C_Widget管理::f_刷新置层(uint32 层) {
	for (auto& e : m_帧渲染层[层]->m_渲染区域) {
		e.first->m_更新下层绘制 = true;
		e.second.m_重排序 = true;
	}
	m_帧渲染层[层]->m_帧累计 = 0;
}

void C_Widget管理::f_设置渲染层大小(uvec2 分辨率) {
	uint32 num = m_帧渲染层.size();
	
	视口.x = 0;
	视口.y = 0;
	视口.width = 分辨率.x;
	视口.height = 分辨率.y;
	视口.minDepth = 0;
	视口.maxDepth = 1;

	m_模糊纹理大小 = 分辨率 >> 2;
	m_模糊纹理大小 /= 16;
	m_模糊纹理大小 *= 16;
	m_模糊纹理大小 += 16;


	//f_surface_重置平面帧大小(m_UICtx->m_Ctx, m_sruface, 分辨率);

	for (uint32 i = 0; i < num; ++i) {
		m_帧渲染层[i]->f_设置层分辨率(m_UICtx->m_Ctx, 分辨率, m_模糊纹理大小);
	}
	
	f_纹理集_刷新所有纹理信息(m_模糊写入纹理集);
	f_纹理集_刷新所有纹理信息(m_模糊采样纹理集);

	f_纹理集_刷新所有纹理信息(m_合成写入纹理集);
	f_纹理集_刷新所有纹理信息(m_合成采样纹理集);
}

void C_Widget管理::f_绘制子组件(C_Widget* self) {
	if (self->m_开启渲染) {
		S_Rect2D 裁剪;

		if (self->m_使用父组件裁剪 && self->m_父部件) {
			裁剪 = f_widget_get裁剪(self->m_父部件);
		} 
		else {
			裁剪 = f_widget_get裁剪(self);
		}

		if (self->m_画布) {
			f_vg_setScissor(m_UICtx->m_Ctx, &裁剪);
			f_vg_render2(m_UICtx->m_Ctx, *self->m_画布, E_管线槽::e_UI渲染);
		}
	}
}

//void C_Widget管理::f_合成图层() {
//	f_纹理槽_设置纹理集(m_合成纹理绑定槽, m_模糊写入纹理集, 0, DEF_binding_L3_ArrayImage);
//	f_纹理槽_设置纹理集(m_合成纹理绑定槽, m_模糊采样纹理集, 1, DEF_binding_L3_ArraySampler);
//	
//	//VkWriteDescriptorSet writes[2] = {};
//	//f_纹理槽_设置GPU参数(m_纹理绑定槽, writes[0], *m_DS, 0);
//	f_vg_CompositionBegin(m_图层累计混合);
//	f_vg_Composition(this);
//	
//	f_vg_end(m_UICtx->m_Ctx, 1);
//}

C_Widget管理* f_ui_当前窗口管理() {
	return g当前窗口GM;
}







static void on_行编辑框变换(C_Widget* self) {
	auto* rf = f_vk_get绘图框架((*self));
	float dpi = self->m_UIctx->m_DPI;

	auto* 背景 = f_widget_getSurface2D(self, 0);
	auto* 字符 = f_widget_getSurface2D(self, 1);
	//auto* 线段 = f_widget_getSurface2D(self, 2);

	auto& box = *dynamic_cast<C_文本框*>(self);

	//auto txt = f_ui_get编辑框文本(self);
	//vec2 绘制区域大小 = self->m_Size;

	S_2DConvexRect	区域[2];
	S_GPU内存块*	形状[2];
	vec2			位置[2];
	S_2D颜色包		颜色[2];

	区域[0] = {};
	区域[1] = {};
	位置[0] = {};
	位置[1] = {};

	区域[0].size = self->m_Size;
	区域[0].radius = { S_UI主题::ui_面板圆角半径 * dpi, S_UI主题::ui_面板圆角半径 * dpi };
	区域[0].AA_type = { 1, 0 };
	形状[0] = self->m_图元形状;
	颜色[0] = S_2D颜色包(S_UI主题::uic_数值编辑框开启编辑背景);
	

	int32 框选数量 = box.m_选取.结束行列.x - box.m_选取.开始行列.x;

	if (框选数量) {
		if (box.m_选取.开始行列.y == box.m_选取.结束行列.y) {
			位置[1].x = f_vg_getStringSize(*box.m_字体, box.m_Text.substr(0, box.m_选取.开始行列.x + 1), box.m_Size.y, box.m_字间距*dpi);
			区域[1].size.x = f_vg_getStringSize(*box.m_字体, box.m_Text.substr(box.m_选取.开始行列.x, 框选数量), box.m_Size.y, box.m_字间距*dpi);
		}
		else {
			
		}
		//位置[1].x += f_vg_StringDrawOffset(box.m_Size.y);
		区域[1].size.x += box.m_字间距*dpi*0.5;
		区域[1].size.y = box.m_Size.y;

		形状[1] = &self->m_UIctx->m_Ctx.m_几何图形->m_平面矩形;
		颜色[1] = S_2D颜色包(S_UI主题::uic_行编辑框选框);
	}
	else {
		box.f_set光标绘制坐标(box.m_Size.y);

		区域[1].size = {2, self->m_Size.y};
		区域[1].AA_type = { 1, 0 };

		位置[1] = box.g光标绘制位置;
		形状[1] = &self->m_UIctx->m_Ctx.m_几何图形->m_平面矩形;
		颜色[1] = S_2D颜色包(S_UI主题::uic_行编辑框光标);
	}


	f_vg_drawConvex(*背景, 2, 形状, 区域);
	f_vg_tranform(*背景, 2, 位置);
	f_vg_color(*背景, 2, 颜色);


	std::u16string	字符串 = f_ui_get编辑框文本(self);
	S_Rect2Df		字符区域 = {{}, self->m_Size };
	
	f_vg_drawString(*字符, 字符串, 字符区域, S_UI主题::uic_文字颜色, E_对齐方式::e_左对齐, {S_UI主题::ui_文字间隔, E_方向::e_横向 });

}


void C_Widget管理::f_绘制编辑框文本编辑() {
	auto* 背景 = f_vg_genConvex(m_UICtx->m_Ctx, *m_文本编辑框画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	auto* 文本 = f_vg_genString(m_UICtx->m_Ctx, *m_文本编辑框画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, S_UI主题::ui_默认字体);
	//auto* 线段 = f_vg_genLine(m_UICtx->m_Ctx, *m_文本编辑框画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
}

void C_Widget管理::f_绑定绘制编辑框(C_Widget* w) {
	w->f_添加画布(m_文本编辑框画布);
	w->mf_变换 = on_行编辑框变换;

	//auto gm = w->f_get窗口管理();
	//w->m_渲染层 = gm->f_添加渲染层(gm->m_顶层渲染层, w);
	f_widget_加入顶层绘图(w);

	//f_widget_更新绘制(w);
	std::cout<<"编辑框开启\n";
}

void C_Widget管理::f_解绑编辑框绘制(C_Widget* w) {
	w->f_移除画布();
	w->mf_变换 = nullptr;

	auto gm = w->f_get窗口管理();
	gm->f_移除渲染层(gm->m_顶层渲染层, w);

	//f_widget_更新绘制(w);
	std::cout<<"编辑框关闭\n";
}


S_TexArrayRes* C_Widget管理::f_加载图标(std::string 组名称, std::string path) {
	if (m_UICtx->m_Mat->m_ICOs.find(组名称) == m_UICtx->m_Mat->m_ICOs.end()) {
		m_UICtx->m_Mat->m_ICOs[组名称] = S_TexArrayRes();

		std::vector<std::string> 目录文件名;
		uint32 num = f_file_get目录下所有文件(path, 目录文件名);
		assert(num);

		if (num > 0) {
			auto& tex = m_UICtx->m_Mat->m_ICOs[组名称];
			
			tex.m_Tex = f_fromFile创建纹理数组(m_UICtx->m_Ctx, m_UICtx->m_Mat->m_采样器, 目录文件名);
			for (uint32 i = 0; i < num; ++i) {
				tex.m_Name[f_file_get无后缀文件名(目录文件名[i])] = i;
			}
		}
	}

	return &(m_UICtx->m_Mat->m_ICOs[组名称]);
}













void f_widget_set绘制根区域组件(C_Widget* self, C_Widget* w) {
	self->m_区域帧缓存根 = w;
	self->m_更新下层绘制 = true;

	auto gm = self->f_get窗口管理();
	if (gm) {
		gm->f_添加渲染层(self->m_渲染层, self);

		if (w) {
			gm->m_帧渲染层[self->m_渲染层]->m_顶层 = false;
		}
		else {
			gm->m_帧渲染层[self->m_渲染层]->m_顶层 = true;
		}
	}
	
	//self->f_get窗口管理()->f_移除渲染组件(self->m_渲染层, self);
	//if (self->m_区域帧缓存根 && self->m_画布) {
	//	self->f_get窗口管理()->f_移除渲染组件(self->m_渲染层, self);
	//}
	//for (auto& e : self->m_子组件) {
	//	if (e->m_渲染层 == w->m_渲染层) {
	//		f_widget_set绘制根区域组件(e, w);
	//	}
	//}
}

void f_widget_加入顶层绘图(C_Widget* self) {
	auto gm = self->f_get窗口管理();
	if (gm) {
		self->m_渲染层 = gm->m_顶层渲染层;
		f_widget_set绘制根区域组件(self, nullptr);
		self->m_区域帧缓存根 = self;

		gm->f_刷新置层(self->m_渲染层);
	}
}

uint8 f_widget_top_push(C_Widget管理* gm, C_Widget* w) {
	gm->gTopWidget[gm->gTopWidgetCount] = w;
	w->m_渲染层 = gm->f_添加渲染层(gm->m_顶层渲染层, w);
	return ++gm->gTopWidgetCount;
}

uint8 f_widget_top_push(C_Widget* w, uint8 offset) {
	C_Widget管理* gm = w->f_get窗口管理();
	if (gm) {
		gm->gTopWidget[offset] = w;
		gm->gTopWidgetCount = offset + 1;
		w->m_渲染层 = gm->f_添加渲染层(gm->m_顶层渲染层, w);
		return gm->gTopWidgetCount;
	}
	return 0;
}

uint8 f_widget_top_close(C_Widget管理* gm) {
	if (gm->gTopWidgetCount > 0) {
		//gm->gTopWidgetCount = 0;
		--gm->gTopWidgetCount;
		gm->f_裁剪层(gm->m_顶层渲染层);
		gm->gTopWidget[gm->gTopWidgetCount] = 0;
	}
	return gm->gTopWidgetCount;
}

uint8 f_widget_顶层窗口_pop(C_Widget管理* gm, uint8 钳制位置) {
	if (gm) {
		if (钳制位置) {
			if (钳制位置 < gm->gTopWidgetCount) {
				for (int32 i = gm->gTopWidgetCount - 1; i >= 钳制位置; --i) {
					gm->f_移除渲染层(gm->m_顶层渲染层, gm->gTopWidget[i]);
				}
				gm->gTopWidgetCount = 钳制位置;
			}
		}
		else {
			gm->gTopWidgetCount = 0;
			gm->f_记录裁剪层(gm->m_顶层渲染层);
		}
	}
	return 0;
}

S_需更新部件 f_widget_getTop(C_Widget管理* gm) {
	return { gm->gTopWidget, gm->gTopWidgetCount };
}

C_Widget* f_widget_getBack(C_Widget管理* gm) {
	if (gm->gTopWidgetCount > 0) {
		return gm->gTopWidget[--gm->gTopWidgetCount];
	}
	return nullptr;
}

uint8 f_widget_getTopNum(C_Widget管理* gm) {
	if (gm) {
		return gm->gTopWidgetCount;
	}
	return 0;
}




uint8 f_widget_hover_push(C_Widget管理* gm, C_Widget* w) {
	gm->gHoverWidget[gm->gHoverWidgetCount] = w;
	w->m_渲染层 = gm->f_添加渲染层(w->m_渲染层, w);
	return ++gm->gHoverWidgetCount;
}

uint8 f_widget_hover_pop(C_Widget管理* gm,uint8 钳制位置) {
	if (钳制位置) {
		if (钳制位置 < gm->gHoverWidgetCount) {
			for (int32 i = gm->gHoverWidgetCount - 1; i >= 钳制位置; --i) {
				gm->f_移除渲染层(gm->gTopWidget[i]->m_渲染层, gm->gTopWidget[i]);
			}
			gm->gHoverWidgetCount = 钳制位置;
		}
	}
	else {
		gm->gHoverWidgetCount = 0;
		gm->f_记录裁剪层(gm->m_顶层渲染层);
	}
	return gm->gHoverWidgetCount;
}

uint8 f_widget_hover_close(C_Widget管理* gm) {
	if (gm->gHoverWidgetCount > 0) {
		--gm->gHoverWidgetCount;
		gm->f_裁剪层(gm->m_顶层渲染层);
		gm->gTopWidget[gm->gHoverWidgetCount] = 0;
	}
	return gm->gHoverWidgetCount;
}

C_Widget* f_widget_hover_get(C_Widget管理* gm, uint32 index) {
	return gm->gTopWidget[index];
}





void f_widget_remove子部件(C_Widget* self, uint32* id, bool 即时销毁) {
}

void f_Widget_鼠标位置视口缩放(C_Widget* self, const vec2& 缩放量) {
	auto 鼠标局部位置 = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);

	vec2 新大小 = self->m_Size * 缩放量;
	vec2 差 = self->m_Size - 新大小;

	vec2 偏移权重 = 鼠标局部位置 / self->m_Size;

	self->m_Pos += 差*偏移权重;
	self->m_Size = 新大小;

	self->m_Scale *= 缩放量;
	self->m_更新绘制属性 = true;
}

void f_Widget_保持偏移比例(C_Widget* pw, C_Widget* self, uint32 方向位域) {
	//vec2 大小差 = self->m_扩展视口属性->m_大小;
	vec2 大小差; // = self->m_父部件->m_Size;

	if (E_方向位域::e_横向位域 & 方向位域) {
		大小差.x = pw->m_Size.x - self->m_Size.x;
		//self->m_Pos.x -= 大小差.x * 0.5;

	}
	if (E_方向位域::e_纵向位域 & 方向位域) {
		大小差.y = pw->m_Size.y - self->m_Size.y;
		//self->m_Pos.y -= 大小差.y * 0.5;
	}
	
	//self->m_扩展视口属性->m_大小 = self->m_Size;
}

void f_Widget_视口偏移(C_Widget* self, float32 x, float32 y) {
	self->m_扩展视口属性->m_中心.x += x;
	self->m_扩展视口属性->m_中心.y += y;

	f_Widget_计算偏移比例(self);
}

void f_widget_clear焦点组件() {
	//C_Widget::g_焦点数量 = 0;
}

uint32 f_widget_取组件位置索引(C_Widget* self, C_Widget* 要查找的组件) {
	auto e = self->f_get更新组件();
	for (uint32 i = 0; i < e.m_Num; ++i) {
		if(e.m_W[i] == 要查找的组件) return i;
	}
	return -1;
}

void f_widget_移动层(C_Widget* self, uint32 源组件位置索引, uint32 目标位置索引) {
	auto e = self->f_get更新组件();
	if(源组件位置索引 > 目标位置索引 && 目标位置索引 < e.m_Num) return;

	C_Widget* 源组件 = e.m_W[源组件位置索引];
	self->m_子组件.erase(self->m_子组件.begin() + 源组件位置索引);
	self->m_子组件.insert(self->m_子组件.begin() + 目标位置索引, 源组件);
}

void f_widget_更新渲染层(C_Widget* self) {
	if (self->m_渲染层 < self->m_UIctx->m_GM->m_帧渲染层.size()) {
		auto& 层 = *self->m_UIctx->m_GM->m_帧渲染层[self->m_渲染层];
		层.m_帧累计 = 0;
		//self->m_更新下层绘制 = true;

		if (层.m_渲染区域.find(self->m_区域链接根) != 层.m_渲染区域.end() && self->m_区域链接根->m_渲染层 == self->m_渲染层) {
			self->m_区域链接根->m_更新下层绘制 = true;
			self->m_区域链接根->m_更新绘制属性 = true;
			//层.m_渲染区域[self->m_区域链接根].m_重排序 = true;
		}
	}
}

void f_widget_重构渲染层(C_Widget* self) {
	if (self->m_渲染层 < self->m_UIctx->m_GM->m_帧渲染层.size()) {
		auto& 层 = *self->m_UIctx->m_GM->m_帧渲染层[self->m_渲染层];
		for (auto& e : 层.m_渲染区域) {
			e.second.m_重排序 = true;
		}
	}
}




void f_widget_构建滚动行组件(C_Widget* self, float32 行高度) {
	uint32 组件数量 = self->m_Size.y / 行高度 + 2;
	uint32 num = self->f_get子部件数量();

	for (uint32 i = num; i < 组件数量; ++i) {
		C_Widget* item = new C_Widget;
		self->f_添加子组件(item);
	}

	auto e = self->f_get更新组件();

	for (uint32 i = 0; i < 组件数量; ++i) {
		e.m_W[i]->m_实例ID = i;
	}

}

void f_Widget_应用视口滚动(C_Widget* self, C_Widget* view, E_方向 方向) {
	if (方向 == E_方向::e_纵向) {
		
		float32 y = view->m_Pos.y;
		if (y > 0) {
			view->f_setY(0);
		} 
		else if (self->m_父部件 && view->m_Size.y + y < self->m_父部件->m_Size.y) {
			view->f_setY(-(self->m_Size.y - self->m_父部件->m_Size.y));
		}

		view->f_setY(view->m_Pos.y + C_Widget::g_鼠标.lZ * 30);
	}
	
	view->m_更新绘制属性 = true;
}

void f_Widget_限定视口滚动(C_Widget* self, float32 父组件大小, float32* view, E_方向 方向, float32 s) {
	self->m_更新绘制属性 = true;

	if (方向 == E_方向::e_纵向) {
		if (self->m_Size.y + (*view) <= 父组件大小) {
			(*view) = -(self->m_Size.y - 父组件大小);
		}

		if ((*view) > 0) {
			(*view) = 0;
		}
	}
}










vec2 f_widget_取鼠标在后光标位置(C_文本框* self, const vec2& 鼠标位置, E_对齐方式 对齐方式, vec2 offset, const std::u16string& text) {
	vec2 选框;
	uint16 文字索引位置 = 0;

	选框.x = 鼠标位置.x;
	选框.y = 文字索引位置;
	float32 光标位移 = offset.x;

	auto* rf = f_vk_get绘图框架((*self));
	auto& font = rf->m_字体[u"雅黑"];
	
	
	uint32 num = text.size();
	switch (对齐方式) {
		case E_对齐方式::e_左对齐:
		{
			float32 width = 0;
			for (uint32 i = 0; i < num; ++i) {
				//width = f_surface_get字符串宽度(*self->m_字体, text[i], S_UI主题::ui_文字间隔);
				width = f_vg_getStringSize(font, std::u16string(1, text[i]), self->m_字号, S_UI主题::ui_文字间隔);

				if (鼠标位置.x > 光标位移 + width * 0.5f) {
					文字索引位置 = i;

					
				} else {
					break;
				}
				光标位移 += width;
			}
			
			//if (num && 鼠标位置.x + width * 0.5f > 光标位移) {
			//	++文字索引位置;
			//}
		}
		break;
		case E_对齐方式::e_据中对齐:
		{
			float32 width = 0;
			for (uint32 i = 0; i < num; ++i) {
				//width = f_surface_get字符串宽度(*self->m_字体, text[i], S_UI主题::ui_文字间隔);
				width = f_vg_getStringSize(font, std::u16string(1, text[i]), self->m_字号, S_UI主题::ui_文字间隔);
				if (鼠标位置.x > 光标位移 + width * 0.5) {
					文字索引位置 = i;
				}
				else {
					break;
				}

				光标位移 += width;
			}

			//if (num && 鼠标位置.x + width * 0.5f > 光标位移) {
			//	++文字索引位置;
			//}
		}
		break;
		default:
			break;
	}
	
	选框.x = 光标位移;
	选框.y = 文字索引位置;

	return 选框;
}

int32 f_widget_从鼠标取光标索引(C_文本框* self, const vec2& 鼠标位置, E_对齐方式 对齐方式, std::u16string text, float32 行高度) {
	int32 文字索引位置 = 0;
	

	float32 dpi = self->m_UIctx->m_DPI;
	float32 间隔 = S_UI主题::ui_文字间隔 * dpi;
	float32 光标位移 = f_vg_StringDrawOffset(行高度);
	float32 width = 0;

	auto* rf = f_vk_get绘图框架((*self));
	auto& font = *self->m_字体;

	uint32 num = text.size();
	text.push_back(0);

	switch (对齐方式) {
		case E_对齐方式::e_左对齐: {
		
			for (uint32 i = 0; i < num; ++i) {
				float32 width = f_vg_getCharWidth(font, text[i], self->m_字号 * dpi);

				if (鼠标位置.x > 光标位移 + width*0.5) {
					文字索引位置 = i + 1;
				}
				else {
					break;
				}
				光标位移 += width + 间隔;

			}
			break;
		}
	
		case E_对齐方式::e_据中对齐: {
			for (uint32 i = 0; i < num; ++i) {
				width = f_vg_getStringSize(font, std::u16string(1, text[i]), self->m_字号, S_UI主题::ui_文字间隔);

				if (鼠标位置.x > 光标位移 + width * 0.5) {
					文字索引位置 = i;
				}
				else {
					break;
				}
				光标位移 += width;
			}
			break;
		}
	
		default:
			break;
	}
	
	return 文字索引位置;
}

void f_widget_选择编辑文本(C_文本框* self, const uvec2& 区间) {
	//S_文本选框 选框;
	uint16 文字索引位置 = 0;

	auto* rf = f_vk_get绘图框架((*self));
	auto& font = rf->m_字体[u"雅黑"];

	//选框.x = 光标位置.x;
	//选框.y = offset.y;
	float32 光标位移 = 0;

	uint32 num = self->m_Text.size();
	switch (self->m_对齐方式) {
		case E_对齐方式::e_左对齐: {
			for (uint32 i = 0; i < num; ++i) {
				float32 width = width = f_vg_getStringSize(font, std::u16string(1, self->m_Text[i]), self->m_字号, S_UI主题::ui_文字间隔);

				
			}
			break;
		}
		
		case E_对齐方式::e_据中对齐: {
			float32 width = f_vg_getStringSize(*self->m_字体, self->m_Text, self->m_字号, S_UI主题::ui_文字间隔);

			//self->m_行选框左边和右边.x = (self->m_Size.x - width) * 0.5f;
			//self->m_行选框左边和右边.y = self->m_行选框左边和右边.x;
			//
			//
			//num = DEF_Min(区间.y, num);
			//
			//self->g选择文本ID区间.x = 区间.x;
			//self->g选择文本ID区间.y = num;
			//for (uint32 i = 区间.x; i < num; ++i) {
			//	float32 width = f_vg_getCharWidth(*self->m_字体, self->m_Text[i], self->m_字号);
			//
			//	if (i < 区间.x) {
			//		self->m_行选框左边和右边.x += width;
			//		self->m_行选框左边和右边.y += width;
			//	}
			//	else {
			//		self->m_行选框左边和右边.y += width;
			//	}
			//}
			break;
		}
		
		default:
			break;
	}
	
}


















static E_事件是否传递 on_文本框鼠标点击(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_文本框* editBox = dynamic_cast<C_文本框*>(self);

	if (self->f_get窗口管理()->m_当前独占操作文本框 && self->f_get窗口管理()->m_当前独占操作文本框 != editBox) {
		self->f_get窗口管理()->m_当前独占操作文本框->f_输入完成();
	}

	//editBox->f_输入完成();
	editBox->f_开启输入();
	//std::cout << "on_文本框鼠标点击" << std::endl;
	return E_事件是否传递::e_事件传递_终止;
}

C_文本框::C_文本框(S_UI渲染环境& ctx, std::u16string 字体名称) : C_Widget(&ctx), m_选择开启(false) {
	assert(ctx.m_GM);
	mf_文本输入 = nullptr;
	mf_文本过滤 = nullptr;
	mf_文本完成 = nullptr;
	mf_行输入回调 = nullptr;
	mf_字符输入回调 = nullptr;
	mf_光标改变回调 = nullptr;

	mf_鼠标点击	= on_文本框鼠标点击;
	m_对齐方式	= E_对齐方式::e_据中对齐;

	m_光标坐标索引 = {};
	m_选取 = {};

	m_行距 = 4;
	m_字间距 = 2;
	m_字号 = 24;

	m_文字边间距.x = 10;
	m_文字边间距.y = 2;

	m_选取.结束行列 = m_选取.开始行列 = { 0, 0 };

	m_文档 = &m_内部文档;
	f_setSize({ 512,256 });
	m_颜色A = S_UI主题::uic_行编辑框背景;
	m_颜色B = {};
	m_图元形状 = &m_UIctx->m_Ctx.m_几何图形->m_平面圆角矩形;

	auto* rf = f_vk_get绘图框架((*this));
	m_字体 = &rf->m_字体[字体名称];


}

C_文本框::~C_文本框() {
}

void C_文本框::f_开启输入() {
	f_get窗口管理()->m_当前独占操作文本框 = this;
	f_置光标索引();
	
	m_开启编辑 = true;
	m_UIctx->m_GM->f_更新层(m_渲染层);
}

void C_文本框::f_输入完成() {
	m_开启编辑 = false;
	
	f_get窗口管理()->m_当前独占操作文本框 = nullptr;
	f_get窗口管理()->m_当前文本输入框 = nullptr;
	m_选取.开始行列 = {};
	m_选取.结束行列 = {};

	m_更新绘制属性 = true;
}

vec2 C_文本框::f_set光标绘制坐标(float32 行高) {
	float32 dpi = m_UIctx->m_DPI;

	if (m_光标坐标索引.x <= 0) {
		C_文本框::g光标绘制位置.x = -m_字间距*dpi;
	}
	else {
		C_文本框::g光标绘制位置.x = f_vg_getStringSize(*m_字体, m_Text.substr(0, m_光标坐标索引.x), 行高, m_字间距*dpi);
	}
	C_文本框::g光标绘制位置.x += f_vg_StringDrawOffset(行高);
	return C_文本框::g光标绘制位置;
}


void C_文本框::f_填充文本(const std::u16string& text) {
	m_Text = text;
	m_光标坐标索引.x = text.size();

	f_set对齐偏移();
	
	m_更新绘制属性 = true;
}

void C_文本框::f_set对齐偏移() {
	float32 width = 0;
}

S_文本前后 C_文本框::f_get当前输入前后字符() {
	S_文本前后 前后 = {};


	int32 IDx = m_光标坐标索引.x - 1;
	int32 IDy = m_光标坐标索引.y;
	if (IDx < 0) {
		--IDy;
		if (IDy >= 0) {
			if (m_文档->m_文本块[IDy].m_一行.size()) {
				前后.前 = m_文档->m_文本块[IDy].m_一行.back();
			}
		}
	}
	else {
		if (IDx < m_文档->m_文本块[IDy].m_一行.size()) {
			前后.前 = m_文档->m_文本块[IDy].m_一行[IDx];
		}
		else {
			前后.前 = m_文档->m_文本块[IDy].m_一行.back();
		}
	}

	IDx = m_光标坐标索引.x + 1;
	IDy = m_光标坐标索引.y;
	if (IDx >= m_文档->m_文本块[IDy].m_一行.size()) {
		if (IDy < m_文档->m_文本块.size()) {
			前后.后 = f_str_从跳过字符取字符(m_文档->m_文本块[IDy].m_一行, u"\n ");
			//前后.后 = m_文档->m_文本块[IDy][0];
		}
		else {
			++IDy;
			if (m_文档->m_文本块[IDy].m_一行.size()) {
				前后.后 = f_str_从跳过字符取字符(m_文档->m_文本块[IDy].m_一行, u"\n ");
			}
		}
	}
	else {
		前后.后 = m_文档->m_文本块[IDy].m_一行[IDx];
	}

	return 前后;
}

wchar_t C_文本框::f_get行头字符(int32 行) {
	if (行 < m_文档->m_文本块.size()) {
		if(m_文档->m_文本块[行].m_一行.size()) return m_文档->m_文本块[行].m_一行.front();
	}
	return 0;
}

wchar_t C_文本框::f_get行尾字符(int32 行) {
	if (行 < m_文档->m_文本块.size()) {
		if (m_文档->m_文本块[行].m_一行.size()) return m_文档->m_文本块[行].m_一行.back();
	}
	return 0;
}

uint32 C_文本框::f_get同样字符数量(int32 行, int32 offset, wchar_t txt) {
	uint32 num = 0;
	if (行 < m_文档->m_文本块.size()) {
		
		for (auto e : m_文档->m_文本块[行].m_一行) {
			if (e != txt) return num;
			++num;
		}
	}
	return num;
}










void f_widget_开始输入法() {
	g是否使用输入法 = true;
	//g输入法输入字符数量 = 0;
}

void f_widget_结束输入法() {
	g是否使用输入法 = false;
	//g输入法输入字符数量 = 0;
	g输入法文本.clear();
}

void f_widget_结束输入状态() {
	if(!g是否使用输入法) g输入法有输入 = false;
}

bool f_widget_输入法是否有输入() {
	if(g输入法正在输入的字符 == 2 || g输入法正在输入的字符 == 1) --g输入法正在输入的字符;
	return g输入法有输入 && g输入法正在输入的字符 > 0;
}

ivec2 f_widget_get输入法窗口位置() {
	return g输入法窗口位置;
}

void f_widget_set输入法窗口位置(const ivec2& pos) {
	g输入法窗口位置 = pos;
}

void f_widget_发射输入法文本(const std::u16string& str) {
	g输入法文本 = str;
}

std::u16string f_widget_get输入法文本() {
	std::u16string t = g输入法文本;
	//if(g输入法文本.size()) g输入法输入字符数量 = 0;
	g输入法文本.clear();
	g输入法正在输入的字符 = 0;
	return t;
}

bool f_widget_是否处在输入法状态() {
	return g是否使用输入法;
}

void f_widget_set当前正在输入的文本(const std::wstring& txt) {
	g输入法正在输入的字符 = txt.size();
}



void f_widget_set当前窗口矩形(const vec4& 区域) {
	//g_当前窗口区域 = 区域;
}

vec4 f_widget_get当前窗口矩形() {
	return {};
}

void f_widget_交换顶层组件(C_Widget管理* gm, uint32 新顶层组件ID) {
	if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, false);
	gm->m_Root = gm->m_根部件切换组[新顶层组件ID];
	if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, true);
}

void f_widget_交换顶层组件(C_Widget* w, uint32 新顶层组件ID) {
	auto* gm = w->f_get窗口管理();
	if (gm) {
		if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, false);
		gm->m_Root = gm->m_根部件切换组[新顶层组件ID];
		if (gm->m_Root->mf_打开关闭) gm->m_Root->mf_打开关闭(gm->m_Root, true);
	}
}

void f_widget_移除组件链接(C_Widget* self) {
	if (self->m_PropUILink && self->m_PropUILink->m_LinkWidget) {
		self->m_PropUILink->m_LinkWidget->erase(self);
	}
}

void f_widget_移除组件链接(std::vector<C_Widget*>& self) {
	for (auto& e : self) f_widget_移除组件链接(e);
}

void f_widget_属性链接组件(S_Props& prop, const std::vector<C_Widget*>& ws) {
	if(prop.m_UI->m_LinkWidget == nullptr) prop.m_UI->m_LinkWidget = new std::set<struct C_Widget*>();

	for (auto& e : ws) {
		(*prop.m_UI->m_LinkWidget).insert(e);
	}
}

void f_widget_属性断开组件(S_Props& prop, const std::vector<C_Widget*>& ws) {
	if (prop.m_UI->m_LinkWidget == nullptr) return;

	for (auto& e : ws) {
		(*prop.m_UI->m_LinkWidget).erase(e);
	}
}

void f_widget_解绑属性(C_Widget* self, S_Props& prop) {
	if (prop.m_UI && prop.m_UI->m_LinkWidget && prop.m_UI->m_LinkWidget->find(self) != prop.m_UI->m_LinkWidget->end()) {
		prop.m_UI->m_LinkWidget->erase(self);
	}
}

void f_widget_绑定属性(C_Widget* self, S_Props& prop) {
	if (prop.m_UI && prop.m_UI->m_LinkWidget) {
		prop.m_UI->m_LinkWidget->insert(self);
	}
}




static int32 g定时改变时长 = 600;
static DWORD WINAPI f_widget_定时关闭弹出组件(LPVOID pParam) {
	int i = 0;

	Sleep(g定时改变时长);
	if (C_Widget::g_是否打开了弹出窗口) {
		C_Widget::g_是否打开了弹出窗口 = false;
		f_widget_顶层窗口_pop(f_ui_当前窗口管理(), 0);
	}

	return 0;
}

void f_widget_线程定时关闭弹出组件(int32 延时) {
	g定时改变时长 = 延时;
	C_Widget::g_是否打开了弹出窗口 = true;
	auto hThread = CreateThread(NULL, 0, f_widget_定时关闭弹出组件, NULL, 0, NULL);
}

void f_widget_取消定时关闭弹出组件() {
	C_Widget::g_是否打开了弹出窗口 = false;
}



static vec2 g鼠标固定位置;
static bool g固定鼠标 = false;
void f_widget_set鼠标位置(const vec2* pos){
	SetCursorPos(pos->x, pos->y);
}

void f_widget_开始固定鼠标位置() {
	POINT 坐标;
	GetCursorPos(&坐标);
	g鼠标固定位置.x = 坐标.x;
	g鼠标固定位置.y = 坐标.y;
	g固定鼠标 = true;
}

void f_widget_固定鼠标位置() {
	SetCursorPos(g鼠标固定位置.x, g鼠标固定位置.y);
}

void f_widget_结束鼠标固定() {
	g固定鼠标 = false;
}

vec2 f_widget_get鼠标步进() {
	vec2 r{};
	POINT 坐标;
	GetCursorPos(&坐标);
	r.x = 坐标.x - g鼠标固定位置.x;
	r.y = 坐标.y - g鼠标固定位置.y;

	//g鼠标固定位置.x = 坐标.x;
	//g鼠标固定位置.y = 坐标.y;
	SetCursorPos(g鼠标固定位置.x, g鼠标固定位置.y);
	
	return r;
}

void f_widget_set当前激活编辑框(C_Widget* self) {
	C_文本框* editBox = dynamic_cast<C_文本框*>(self);

	if (editBox) {
		if (self->f_get窗口管理()->m_当前独占操作文本框 && self->f_get窗口管理()->m_当前独占操作文本框 != editBox) {
			self->f_get窗口管理()->m_当前独占操作文本框->f_输入完成();
		}

		self->f_get窗口管理()->m_当前独占操作文本框 = editBox;
		editBox->f_开启输入();

		editBox->f_置光标索引();
		editBox->m_选取.开始行列 = { int32(editBox->m_光标坐标索引.x) + 1, int32(editBox->m_光标坐标索引.y) };
		editBox->m_选取.结束行列 = editBox->m_选取.开始行列;

	}
}

